package ru.pb.game.network;

import java.net.InetAddress;
import java.net.InetSocketAddress;

import ru.pb.game.configs.GameNetworkConfig;
import ru.pb.game.network.clients.AuthServerClient;
import ru.pb.game.network.clients.GameClient;
import ru.pb.game.network.engine.AuthServerClientFactory;
import ru.pb.game.network.engine.ClientFactory;
import ru.pb.game.network.engine.auth.AuthServerPacketListenerHandler;
import ru.pb.game.network.engine.client.ClientsPacketListenerHandler;
import ru.pb.game.network.engine.listener.AuthServerListener;
import ru.pb.game.network.protokol.ClientProtocol;
import ru.pb.game.network.protokol.GameProtocol;
import ru.pb.game.network.threading.ThreadPoolManager;
import ru.pb.global.network.engine.NioAcceptor;
import ru.pb.global.network.engine.NioConnector;
import ru.pb.global.network.engine.core.HelperAdapter;
import ru.pb.global.threading.RunnableTask;
import ru.pb.global.utils.ExitCode;

public class GNetworkEngine
{
	private static GNetworkEngine _instance;
	private static final String client = "Открыт порт для подключения игроков сервера: ";

	private NioAcceptor<GameClient> _clientListener;
	private NioConnector<AuthServerClient> _authConnector;

	public static GNetworkEngine getInstance()
	{
		if(_instance == null)
			_instance = new GNetworkEngine();
		return _instance;
	}

	GNetworkEngine()
	{
		try
		{
			InetSocketAddress ad;
			if(GameNetworkConfig.AUTH_SERVER_HOST.equals("*"))
			{
				ad = new InetSocketAddress(GameNetworkConfig.AUTH_SERVER_PORT);
			}
			else
			{
				ad = new InetSocketAddress(InetAddress.getByName(GameNetworkConfig.AUTH_SERVER_HOST), GameNetworkConfig.AUTH_SERVER_PORT);
			}

			AuthServerClientFactory f = new AuthServerClientFactory();
			HelperAdapter<AuthServerClient> a1 = new HelperAdapter<AuthServerClient>(f, f, new AuthServerPacketListenerHandler());

			_authConnector = new NioConnector<AuthServerClient>(a1, ad, new GameProtocol(), 1);
			_authConnector.addListener(new AuthServerListener());
		}
		catch(Exception e)
		{
			System.exit( -1);
		}

		try
		{
			InetSocketAddress address;
			if(GameNetworkConfig.CLIENT_LISTENER_HOST.equals("*"))
			{
				address = new InetSocketAddress(GameNetworkConfig.CLIENT_LISTENER_PORT);
			}
			else
			{
				address = new InetSocketAddress(InetAddress.getByName(GameNetworkConfig.CLIENT_LISTENER_HOST), GameNetworkConfig.CLIENT_LISTENER_PORT);
			}
			ClientFactory gcl = new ClientFactory();
			ClientsPacketListenerHandler gp = new ClientsPacketListenerHandler();
			HelperAdapter<GameClient> adapter = new HelperAdapter<GameClient>(gcl, gcl, gp);
			_clientListener = new NioAcceptor<GameClient>(adapter, address, new ClientProtocol(), 1);

		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.exit(ExitCode.CODE_ERROR.getId());
		}

		bind();

		connect();
	}

	private void bind()
	{
		_clientListener.bind(client);
	}

	public void connect()
	{
		ThreadPoolManager.getInstance().schedule(new RunnableTask()
		{
			@Override
			public void runImpl()
			{
				_authConnector.connect();
			}
		}, 5000);
	}

	public void unbindANDdisconnect()
	{
		_clientListener.shutdown();
		_authConnector.shutdown();
	}
}